#include "GEnginePCH.h"
#include "Support.h"
#include "Entity.h"

void ScaleAndTranslateAndRotate( D3DXMATRIX &world, 
								const D3DXMATRIX& matVP, float ix,float ygrec,
								float zet,float angleX,float angleY,float angleZ,
								float six,float sygrec,float szet)
{
	CalcWorld( world, ix, ygrec, zet, angleX, angleY, angleZ, six, sygrec, szet);
	SetShaderConst( world, matVP);
}
void ScaleAndTranslateAndRotate( D3DXMATRIX &world, const D3DXMATRIX& matVP, const D3DXVECTOR3& vPos, const D3DXVECTOR3& vRot, const D3DXVECTOR3& vScale)
{
	ScaleAndTranslateAndRotate( world, matVP, vPos.x, vPos.y, vPos.z, vRot.x, vRot.y, vRot.z, vScale.x, vScale.y, vScale.z);
}
void ScaleAndTranslateAndRotate( D3DXMATRIX &world, const D3DXMATRIX& matVP, Entity* entity)
{
	ScaleAndTranslateAndRotate( world, matVP, entity->m_vPos, entity->m_vRot, entity->m_vScale );
}
void CalcWorld( D3DXMATRIX &world, float ix,float ygrec,
			   float zet,float angleX,float angleY,float angleZ,
			   float six,float sygrec,float szet)
{
	D3DXMATRIX mat, matWorldX, matWorldY, matWorldZ, matScale;

	D3DXMatrixRotationX(&matWorldX, angleX);
	D3DXMatrixRotationY(&matWorldY, angleY);
	D3DXMatrixRotationZ(&matWorldZ, angleZ);
	D3DXMatrixTranslation(&mat, ix, ygrec, zet);
	D3DXMatrixScaling(&matScale,six,sygrec,szet);

	world=(matScale*matWorldX*matWorldY*matWorldZ*mat);
}
void CalcWorld(D3DXMATRIX &world, const D3DXVECTOR3& vPos, const D3DXVECTOR3& vRot, const D3DXVECTOR3& vScale)
{
	CalcWorld( world, vPos.x, vPos.y, vPos.z, vRot.x, vRot.y, vRot.z, vScale.x, vScale.y, vScale.z);
}
void SetShaderConst( const D3DXMATRIX& world, const D3DXMATRIX& matVP)
{
	D3DXMATRIX matWVP;
	D3DXMatrixMultiplyTranspose( &matWVP, &world, &matVP);
	d3ddev->SetVertexShaderConstantF(0, matWVP, 4);
}
					
inline float DistRayPlane(D3DXVECTOR3& rayOrigin,
                          D3DXVECTOR3& rayVector,
                          D3DXVECTOR3& planeNormal,
                          float planeD)
{
    float cosAlpha;
    float deltaD;


    cosAlpha = D3DXVec3Dot(&rayVector, &planeNormal);

    // parallel to the plane (alpha=90)
    if (cosAlpha==0) return -1.0f;


    deltaD = planeD -  D3DXVec3Dot(&rayOrigin, &planeNormal);
    
    return (deltaD/cosAlpha);
}// End DistRayPlane(..)




//-----------------------------------------------------------------------------
// Name: DoesRayIntersectTriangle()
// Desc: Given a ray origin (orig) and direction (dir), and three vertices of
//       of a triangle, this function returns TRUE and the interpolated texture
//       coordinates if the ray intersects the triangle
//-----------------------------------------------------------------------------
bool DoesRayIntersectTriangle( const D3DXVECTOR3& orig,
                               const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                               D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                               float& t, float& u, float& v )
{
    // Find vectors for two edges sharing vert0
    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    D3DXVECTOR3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    float det = D3DXVec3Dot( &edge1, &pvec );
    if( det < 0.0001f )
        return false;

    // Calculate distance from vert0 to ray origin
    D3DXVECTOR3 tvec = orig - v0;

    // Calculate U parameter and test bounds
    u = D3DXVec3Dot( &tvec, &pvec );
    if( u < 0.0f || u > det )
        return false;

    // Prepare to test V parameter
    D3DXVECTOR3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds
    v = D3DXVec3Dot( &dir, &qvec );
    if( v < 0.0f || u + v > det )
        return false;

    // Calculate t, scale parameters, ray intersects triangle
    t = D3DXVec3Dot( &edge2, &qvec );
    float fInvDet = 1.0f / det;
    t *= fInvDet;
    u *= fInvDet;
    v *= fInvDet;

    return true;
}

void GetRay( int x, int y, D3DXVECTOR3 &vRayOrig, D3DXVECTOR3 &vRayDir,const D3DXMATRIX &matView,const D3DXMATRIX &matProj)
{
	D3DXMATRIX m;

	D3DXVECTOR3 v;
	v.x =  (((2.0f * x)/SCREEN_WIDTH ) -1)/matProj._11;
	v.y = -(((2.0f * y)/SCREEN_HEIGHT) -1)/matProj._22;
	v.z = 1.0f;
	
	D3DXMatrixInverse(&m ,NULL, &matView);
	vRayDir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
	vRayDir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
	vRayDir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;

	D3DXVec3Normalize(&vRayDir,&vRayDir);

	vRayOrig.x = m._41;
	vRayOrig.y = m._42;
	vRayOrig.z = m._43;			
}
void printVector(const D3DXVECTOR3 &vect)
{
	char w[300];
	sprintf_s(w, "%f %f %f ",vect.x, vect.y, vect.z);
	MessageBox( NULL, w , "ERROR", MB_OK | MB_ICONEXCLAMATION );
}
void printMatrix(const D3DXMATRIX &matrix)
{
	char ww[3000];
	sprintf_s(ww, "%f %f %f %f \n %f %f %f %f \n %f %f %f %f \n %f %f %f %f \n ",matrix._11, matrix._12,matrix._13, matrix._14,matrix._21, matrix._22,matrix._23, matrix._24,matrix._31, matrix._32,matrix._33, matrix._34,matrix._41, matrix._42,matrix._43, matrix._44);
	MessageBox( NULL, ww , "ERROR", MB_OK | MB_ICONEXCLAMATION );
}

int RandomInt(int iMin, int iMax)
{
	if (iMin == iMax) return(iMin);
	return((rand() % (abs(iMax-iMin)+1))+iMin);
}

float RandomFloat(float fMin, float fMax)
{
	if (fMin == fMax) return(fMin);
	float fRandom = (float)rand() / (float)RAND_MAX;
	return((fRandom * (float)fabs(fMax-fMin))+fMin);
}
D3DXVECTOR3 RandomVector(D3DXVECTOR3 vMin, D3DXVECTOR3 vMax)
{
	float x = RandomFloat(vMin.x, vMax.x);
	float y = RandomFloat(vMin.y, vMax.y);
	float z = RandomFloat(vMin.z, vMax.z);
	return(D3DXVECTOR3(x,y,z));
}
void MessBox(char *debugStr)
{
	MessageBox( NULL, debugStr, "ERROR", MB_OK | MB_ICONEXCLAMATION );
}
float DistanceSquared2D (const D3DXVECTOR3 &a, const D3DXVECTOR3 &b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.z-b.z)*(a.z-b.z);
}